////////////////////////////////////////////////////////////////////////////////// 	 
//如果需要使用OS,则包括下面的头文件即可.
#include "includes.h"					//ucos 使用	  
#include "sys.h"

#define SYMBOL_GLOBALS
#include "sys_timer.h"
#undef SYMBOL_GLOBALS

static volatile INT32U lo_unElapsedSecs, lo_unElapsedMSecs, lo_unCurSysticks;

static INT8U lo_ubSysticksOfOneUS = 0;						//* 1微秒多少个时钟节拍
static INT8U lo_ubMillisecondsOfOneSystick = 0;		//* 一个时钟节拍多少毫秒
 
//* systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{	
	lo_unCurSysticks++;
	lo_unElapsedMSecs += lo_ubMillisecondsOfOneSystick;
	
	if(!(lo_unCurSysticks % OS_TICKS_PER_SEC))
		lo_unElapsedSecs++;
	
	//* OS开始跑了,才执行正常的调度处理
	if(OSRunning == OS_TRUE)
	{
		OSIntEnter();	//* 进入中断
		OSTimeTick();	//* 调用ucos的时钟服务程序               
		OSIntExit();	//* 触发任务切换软中断
	}
}
			   
void OSSystimerInit(void)
{
	INT32U unReload;
	
	SysTick_Config(500);
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//* 选择外部时钟：HCLK/8
	lo_ubSysticksOfOneUS = (SystemCoreClock / 8) / 1000000;	
	unReload = SystemCoreClock / 8;												//* 每秒钟的计数次数，系统时钟8分频，所以这里除以8
	unReload = unReload / OS_TICKS_PER_SEC;								//* 根据OS的系统时钟节拍数来确定定时器计数值，1 / OS_TICKS_PER_SEC计算一个节拍需要多少秒，与unReload相乘后就是一个定时器滴答多少次正好是一个时钟节拍
																												//* SysTick->LOAD为24位寄存器,最大值:16777216,在72M下,约合1.86s左右	
	
	lo_ubMillisecondsOfOneSystick = 1000 / OS_TICKS_PER_SEC;	//* 代表OS可以延时的最小单位	   

	SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;   					//* 使能Systick中断
	SysTick->LOAD  = unReload - 1; 												//* 每(1 / OS_TICKS_PER_SEC)秒中断一次,也就是进行一次任务调度
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;   					//* 启动Systick定时器
	lo_unElapsedSecs  = 0; 
	lo_unElapsedMSecs = 0; 
	lo_unCurSysticks  = 0;
}								    

void delay_us(INT32U unDelayUS)
{		
	INT32U unTicks;
	INT32U unOldTime, unNowTime, unTimeCnt = 0;
	INT32U unReload = SysTick->LOAD;									//* SysTick->LOAD寄存器设置的计数值	    	 
	
	unTicks   = unDelayUS * lo_ubSysticksOfOneUS;			//* 需要的节拍数
	unTimeCnt = 0;
	OSSchedLock();
	{
		unOldTime = SysTick->VAL; //* 此时的计数值
		while(TRUE)
		{
			unNowTime = SysTick->VAL;
			if(unNowTime != unOldTime)
			{
				if(unNowTime < unOldTime)
					unTimeCnt += unOldTime - unNowTime;
				else 
					unTimeCnt += unReload - unNowTime + unOldTime;	
				
				unOldTime = unNowTime;
				if(unTimeCnt >= unTicks)	//* 延时到达
					break;
			}
		}
	}
	OSSchedUnlock();							    
}

void delay_ms(INT16U usDelayMS)
{	
		//* 如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)	    
	if(OSRunning && !OSIntNesting)
	{		 
		//* 延时的时间大于OS的最少时间周期
		if(usDelayMS >= lo_ubMillisecondsOfOneSystick)		
   			OSTimeDly(usDelayMS / lo_ubMillisecondsOfOneSystick);
		
		//* OS已经无法提供这么小的延时了，剩余的采用普通延时
		usDelayMS %= lo_ubMillisecondsOfOneSystick;
	}
	
	delay_us((INT32U)(usDelayMS * 1000));
}

void DelaymsByCount(INT16U usDelayMS)
{
	INT32U i;
	INT16U j;
	for(j=0;j<usDelayMS;j++)
	{
		for(i=0;i<8100;i++);
	}
}

void DelayusByCount(INT16U usDelayUS)
{
	INT32U	i;
	INT16U j;
	for(j=0;j<usDelayUS;j++)
	{
		for(i=0;i<81;i++);
	}
}

INT32U GetElapsedSecs(void)
{
	return lo_unElapsedSecs;
}

INT32U GetElapsedMSecs(void)
{
	return lo_unElapsedMSecs;
}

INT32U GetCurSysticks(void)
{
	return lo_unCurSysticks;
}
